package com.xxjqr.orderserver.service;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.xxjqr.orderserver.po.Order;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit;


@Service
public class OrderService {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void confirmCallback() {
        //如果消息投递失败，就会有cause
        rabbitTemplate.setConfirmCallback((correlationData,ack,cause)->{

            assert correlationData != null;
            final String data = correlationData.getId();
            final Order order = JSON.parseObject(data, Order.class);
            if (!ack) {
                System.out.println("失败原因:" + cause);
                //判断确认信息是否尝试了3次
                String querySql = String.format("select count(1) from t_order_confirm where order_id = %d and status = 0 and attemp_num < %d;", order.getId(), 3);
                final Integer queryCount = jdbcTemplate.queryForObject(querySql, Integer.class);
                if (queryCount != null && queryCount > 0) {
                    try {
                        TimeUnit.SECONDS.sleep(2);
                        rabbitTemplate.convertAndSend("direct_order_exchange","order",
                                JSON.toJSONString(order),
                                new CorrelationData(data));
                        String updateSQL = "update t_order_confirm set attemp_num = attemp_num+1 where order_id = ?;";
                        jdbcTemplate.update(updateSQL, order.getId());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    System.out.println("MQ队列应答失败，orderId 是：" + order.getId());
                }

            } else {
                try {
                    String updateSQL = "update t_order_confirm set status = 1 where order_id = ?;";
                    final int update = jdbcTemplate.update(updateSQL, order.getId());
                    if (update == 1) {
                        System.out.println("消息成功投递到交换机");
                    } else {
                        System.out.println("修改确认状态失败");
                    }
                } catch (DataAccessException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * @描述 下单service，因为使用了事务，所以一定是该方法走完之后才会commit
     * @码农 丁昌江
     * @日期 2021/5/17 15:14
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean order(Order order) {
        //1 插入订单
        String sql = "INSERT INTO `t_order`  VALUES (?, ?,?);";
        int effectCount = jdbcTemplate.update(sql, order.getId(), order.getUserName(), order.getProduct());
        //2 如果订单插入成功，再讲订单信息推送到派单服务中
        if (effectCount > 0) {
            //使用hutool发送post请求，如果第二个参数是string类型，那么自动是application/json格式；指定读取超时时间3秒
            String post = HttpUtil.post("http://localhost:8082/dispatch", JSON.toJSONString(order),2000);
            return true;
        }
        return false;
    }

    /**
     * @描述 下单service，通过RabbitMQ发送消息到派单服务
     * @码农 丁昌江
     * @日期 2021/5/17 15:14
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean orderByRabbitMQ(Order order) {
        //1 插入订单
        String sql = "INSERT INTO `t_order`(`id`,`user_name`,`product`)  VALUES (?, ?,?);";
        int effectCount = jdbcTemplate.update(sql, order.getId(), order.getUserName(), order.getProduct());
        //2 如果订单插入成功，再讲订单信息推送到派单服务中
        if (effectCount == 1) {
            //3 插入记录订单消息发送到交换机状态的消息
            String confirmSql = "insert into `t_order_confirm` (`id`,`order_id`,`product`,`user_name`) values (?,?,?,?);";
            final int update = jdbcTemplate.update(confirmSql, (int) (Math.random() * 1000), order.getId(), order.getProduct(), order.getUserName());
            if (update == 1) {
                //4 发送消息，我们加入了最后一个参数：相关数据
                System.out.println("rabbitTemplate 发送消息");
                rabbitTemplate.convertAndSend("direct_order_exchange","order",
                        JSON.toJSONString(order),
                        new CorrelationData(JSON.toJSONString(order)));
            }
            return true;
        }
        return false;
    }


}
